import { computed, nextTick, ref, unref, watch } from 'vue'
import {
  tryOnUnmounted,
  useDebounceFn,
  useEventListener,
  useTimeoutFn,
  useBreakpoints
} from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { useThemeConfig } from '@/stores/themeConfig'
import echarts from '@/utils/echarts'
import type { Ref } from 'vue'
import type { Fn } from '@vueuse/core'
import type { EChartsOption } from 'echarts'

export function useECharts(
  elRef: Ref<HTMLDivElement>,
  theme: 'light' | 'dark' | 'default' = 'default'
) {
  const { themeConfig } = storeToRefs(useThemeConfig())
  let chartInstance: echarts.ECharts | null = null
  const cacheOptions = ref({}) as Ref<EChartsOption>
  let removeResizeFn: Fn = () => {}
  const resizeFn: Fn = useDebounceFn(() => {
    resize()
  }, 500)

  const getOptions = computed(() => {
    // if (getDarkMode.value !== 'dark') {
    //     return cacheOptions.value as EChartsOption;
    // }
    return {
      backgroundColor: 'transparent',
      ...cacheOptions.value
    } as EChartsOption
  })

  function initCharts(t = theme) {
    const el = unref(elRef)
    if (!el || !unref(el)) {
      return
    }
    chartInstance = echarts.init(el, t)
    removeResizeFn = useEventListener(window, 'resize', resizeFn)
    const breakpoints = useBreakpoints({
      tablet: 640,
      laptop: 1024,
      desktop: 1280
    })
    const laptop = breakpoints.between('laptop', 'desktop')

    if (laptop.value) {
      useTimeoutFn(() => {
        resizeFn()
      }, 30)
    }
  }

  function setOptions(options: EChartsOption, clear = true) {
    cacheOptions.value = options
    return new Promise((resolve) => {
      if (unref(elRef)?.offsetHeight === 0) {
        useTimeoutFn(() => {
          setOptions(unref(getOptions))
          resolve(null)
        }, 30)
      }
      nextTick(() => {
        useTimeoutFn(() => {
          if (!chartInstance) {
            initCharts(themeConfig.value.isIsDark ? 'dark' : 'light')

            if (!chartInstance) return
          }
          clear && chartInstance?.clear()

          chartInstance?.setOption(unref(getOptions))
          resolve(null)
        }, 30)
      })
    })
  }

  function resize() {
    chartInstance?.resize({
      animation: {
        duration: 300,
        easing: 'quadraticIn'
      }
    })
  }

  watch(
    () => themeConfig.value.isIsDark,
    (dark) => {
      if (chartInstance) {
        chartInstance.dispose()
        initCharts(dark ? 'dark' : 'light')
        setOptions(cacheOptions.value)
      }
    }
  )

  tryOnUnmounted(() => {
    if (!chartInstance) return
    removeResizeFn()
    chartInstance.dispose()
    chartInstance = null
  })

  function getInstance(): echarts.ECharts | null {
    if (!chartInstance) {
      initCharts('default')
    }
    return chartInstance
  }

  return {
    setOptions,
    resize,
    echarts,
    getInstance
  }
}
